package com.coincalf.wallet.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.coincalf.framework.dto.CoinWithdrawDTO;
import com.coincalf.framework.dto.WithdrawResultDTO;
import com.coincalf.framework.enums.CoinWithdrawStatus;
import com.coincalf.framework.enums.TxStateEnum;
import com.coincalf.framework.http.Response;
import com.coincalf.wallet.blockchain.*;
import com.coincalf.wallet.blockchain.bean.TransInfo;
import com.coincalf.wallet.blockchain.client.EosClientSingle;
import com.coincalf.wallet.dto.CoinWithdrawDTOMapper;
import com.coincalf.wallet.entity.CoinWithdraw;
import com.coincalf.wallet.mapper.CoinWithdrawMapper;
import com.coincalf.wallet.service.CoinWithdrawService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.coincalf.wallet.service.UserAddressService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * 数字货币提现 服务实现类
 * </p>
 *
 * @author crow
 * @since 2018-05-16
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class CoinWithdrawServiceImpl extends ServiceImpl<CoinWithdrawMapper, CoinWithdraw> implements CoinWithdrawService {

    @Autowired
    private CoinWithdrawMapper coinWithdrawMapper;
    @Autowired
    private UserAddressService userAddressService;

    @Override
    public Page<CoinWithdraw> selectOutRecharges(Page<CoinWithdraw> page,
                                                 long agencyUserId,
                                                 String userName,
                                                 long orderId,
                                                 Integer status,
                                                 long coinId,
                                                 long parentId,
                                                 String createTime) {
        return null;
    }

    @Override
    public Response selectOutRechargesTotal(long agencyUserId) {
        return null;
    }

    /**
     * 查询链上打币成功，尚未扣除用户资金账户额度
     *
     * @return
     */
    @Override
    public List<CoinWithdrawDTO> queryPendingRecord() {
        EntityWrapper<CoinWithdraw> wrapper = new EntityWrapper<>();
        wrapper.eq("status", CoinWithdrawStatus.SENDING.getCode())
                .orderBy("created", true);
        List<CoinWithdraw> coinWithdraws = baseMapper.selectList(wrapper);
        return CoinWithdrawDTOMapper.INSTANCE.from(coinWithdraws);
    }

    @Override
    public List<CoinWithdrawDTO> queryPassedRecordByCoinName(String coinName) {
        EntityWrapper<CoinWithdraw> wrapper = new EntityWrapper<>();
        wrapper.eq("status", CoinWithdrawStatus.PASSED.getCode())
                .eq("coin_name", coinName)
                .orderBy("created", true);
        List<CoinWithdraw> coinWithdraws = baseMapper.selectList(wrapper);
        return CoinWithdrawDTOMapper.INSTANCE.from(coinWithdraws);
    }

    @Override
    public List<CoinWithdrawDTO> querySendCoiningByCoinName(String coinName) {
        EntityWrapper<CoinWithdraw> wrapper = new EntityWrapper<>();
        wrapper.eq("status", CoinWithdrawStatus.SENDING.getCode())
                .eq("coin_name", coinName)
                .orderBy("created", true);
        List<CoinWithdraw> coinWithdraws = baseMapper.selectList(wrapper);
        return CoinWithdrawDTOMapper.INSTANCE.from(coinWithdraws);
    }

    /**
     * 修改打币状态
     *
     * @param id     主键
     * @param status 状态
     * @return
     */
    @Override
    public boolean modifyWithdrawStatus(Long id, Integer status) {
        return baseMapper.updateStatusById(id, status, "成功") == 1;
    }

    @Override
    public Long applyWithdraw(CoinWithdraw coinWithdraw) {
        boolean exist = userAddressService.selectExist(coinWithdraw.getAddress());
        if (exist) {
            coinWithdraw.setType(0);
        } else {
            coinWithdraw.setType(1);
        }
        baseMapper.insert(coinWithdraw);
        return coinWithdraw.getId();
    }

    @Override
    public TransInfo sendCoin(TransInfo transInfo) {
        String coinName = transInfo.getCoinName();
        if (StringUtils.isEmpty(coinName)) {
            transInfo.setErrMsg("coinName为空");
            transInfo.setStatus(2);
            return transInfo;
        }
        //TODO 合约地址不为空判断 待定 暂时只支持USDT_ERC20代币才能这么写
        if (StringUtils.isEmpty(transInfo.getContractAddress())) {
            if (coinName.equalsIgnoreCase("ETH")) {
                transInfo = EthService.trans(transInfo);
            } else if (coinName.equalsIgnoreCase("BTC")) {
                transInfo = BtcService.trans(transInfo);
            } else if (coinName.equalsIgnoreCase("EOS")) {
                transInfo = EosClientSingle.trans(transInfo);
            } else if (coinName.equalsIgnoreCase("USDT_OMNI")) {
                transInfo = UsdtService.trans(transInfo);
            } else {
                transInfo.setErrMsg("暂不支持该币种提币：" + coinName);
                transInfo.setStatus(TxStateEnum.FAIL.getStatus());
            }
        } else {
            transInfo = Erc20TokenService.getTokenService(transInfo.getContractAddress()).trans(transInfo);
        }
        return transInfo;
    }

    @Override
    public boolean updateTxStatus(WithdrawResultDTO withdrawResultDTO) {
        CoinWithdraw coinWithdraw = super.selectById(withdrawResultDTO.getWithdrawCoinId());
        if (coinWithdraw == null) {
            log.error("提币数据不存在 id={}", withdrawResultDTO.getWithdrawCoinId());
            return false;
        }
        log.info("提币交易：{} 链上转账结果：{} 即将修改提币交易状态", withdrawResultDTO.getWithdrawCoinId(), withdrawResultDTO.getTxStatus());
        coinWithdraw.setStatus(withdrawResultDTO.getTxStatus());
        coinWithdraw.setLastUpdateTime(new Date());
        int i = coinWithdrawMapper.updateById(coinWithdraw);
        if (i == 1) {
            log.info("提币交易：{} 交易状态更新成功", withdrawResultDTO.getWithdrawCoinId());
            return true;
        }
        log.info("提币交易：{} 交易状态更新失败", withdrawResultDTO.getWithdrawCoinId());
        return false;
    }

    @Override
    public boolean updateTxId(WithdrawResultDTO withdrawResultDTO) {
        CoinWithdraw coinWithdraw = super.selectById(withdrawResultDTO.getWithdrawCoinId());
        if (coinWithdraw == null) {
            log.error("提币数据不存在 id={}", withdrawResultDTO.getWithdrawCoinId());
            return false;
        }
        coinWithdraw.setTxid(withdrawResultDTO.getTxId());
        coinWithdraw.setLastUpdateTime(new Date());
        int i = coinWithdrawMapper.updateById(coinWithdraw);
        if (i == 1) {
            log.info("提币交易：{} 交易状态更新成功", withdrawResultDTO.getWithdrawCoinId());
            return true;
        }
        log.info("提币交易：{} 交易状态更新失败", withdrawResultDTO.getWithdrawCoinId());
        return false;
    }

}
